"""
文件名: search.py
描述: 智能搜索功能API路由

本模块包含以下主要功能：
1. 多维度内容搜索（频道、视频、分类）
2. 智能搜索建议和自动完成
3. 高级搜索筛选和排序
4. 搜索历史和偏好记录

依赖模块:
   - fastapi: Web框架路由
   - services: 搜索和相关服务
   - models: 数据模型

使用示例:
   >>> GET /search - 通用搜索
   >>> GET /search/channels - 频道搜索
   >>> GET /search/videos - 视频搜索
   >>> GET /search/suggestions - 搜索建议

注意事项:
   - 搜索结果会根据用户偏好排序
   - 支持全文搜索和精确匹配
   - 搜索历史仅保存最近记录
   - 复杂查询可能影响性能

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from typing import List, Dict, Any, Optional, Union
import uuid
import time

from fastapi import APIRouter, Depends, HTTPException, status, Query
from pydantic import BaseModel

from src.api.dependencies import (
    get_current_user,
    get_search_service,
    get_pagination_params,
)
from src.core.logger import get_logger
from src.models.user import User
from src.models.channel import ChannelSummary
from src.models.video import VideoSummary
from src.models.category import CategorySummary
from src.services.search_service import SearchService
from src.utils.exceptions import (
    ValidationException,
    YouTubeManagerException,
)

logger = get_logger(__name__)

router = APIRouter()


class SearchRequest(BaseModel):
    """搜索请求模型"""
    query: str
    search_type: str = "all"  # all, channels, videos, categories
    filters: Optional[Dict[str, Any]] = None


class SearchResult(BaseModel):
    """搜索结果模型"""
    query: str
    total_results: int
    search_time: float
    channels: List[ChannelSummary] = []
    videos: List[VideoSummary] = []
    categories: List[CategorySummary] = []
    suggestions: List[str] = []


@router.get("", response_model=SearchResult, summary="通用搜索")
async def search_content(
    q: str = Query(..., description="搜索关键词"),
    current_user: User = Depends(get_current_user),
    search_service: SearchService = Depends(get_search_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
    search_type: str = Query("all", description="搜索类型: all, channels, videos, categories"),
    category_id: Optional[uuid.UUID] = Query(None, description="限制搜索的分类范围"),
    published_after: Optional[str] = Query(None, description="发布时间筛选（ISO格式）"),
    duration_filter: Optional[str] = Query(None, description="时长筛选: short, medium, long"),
    sort_by: str = Query("relevance", description="排序方式: relevance, date, views, title"),
    include_suggestions: bool = Query(True, description="是否包含搜索建议"),
) -> SearchResult:
    """
    执行通用内容搜索
    
    Args:
        q: 搜索关键词
        search_type: 搜索类型
        category_id: 分类范围限制
        published_after: 发布时间筛选
        duration_filter: 时长筛选
        sort_by: 排序方式
        include_suggestions: 是否包含建议
        pagination: 分页参数
        
    Returns:
        SearchResult: 搜索结果
    """
    try:
        start_time = time.time()
        
        # 构建搜索筛选器
        filters = {
            "category_id": category_id,
            "published_after": published_after,
            "duration_filter": duration_filter,
        }
        
        # 执行搜索
        results = await search_service.search_content(
            current_user.id,
            query=q,
            search_type=search_type,
            filters=filters,
            sort_by=sort_by,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        search_time = time.time() - start_time
        
        # 获取搜索建议
        suggestions = []
        if include_suggestions and search_time < 2.0:  # 只在快速搜索时提供建议
            suggestions = await search_service.get_search_suggestions(
                current_user.id, q, limit=5
            )
        
        # 记录搜索历史
        await search_service.record_search_history(
            current_user.id, q, search_type, len(results.get("channels", []) + results.get("videos", []))
        )
        
        logger.info(f"搜索执行成功", user_id=str(current_user.id), query=q, results_count=results.get("total", 0))
        
        return SearchResult(
            query=q,
            total_results=results.get("total", 0),
            search_time=search_time,
            channels=results.get("channels", []),
            videos=results.get("videos", []),
            categories=results.get("categories", []),
            suggestions=suggestions,
        )
        
    except ValidationException as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except SearchException as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"搜索执行失败: {e}", user_id=str(current_user.id), query=q)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="搜索服务暂时不可用"
        )


@router.get("/channels", response_model=List[ChannelSummary], summary="频道搜索")
async def search_channels(
    q: str = Query(..., description="搜索关键词"),
    current_user: User = Depends(get_current_user),
    search_service: SearchService = Depends(get_search_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
    category_id: Optional[uuid.UUID] = Query(None, description="限制搜索的分类范围"),
    subscriber_count_min: Optional[int] = Query(None, description="最小订阅数筛选"),
    sort_by: str = Query("relevance", description="排序方式: relevance, subscribers, name, recent"),
) -> List[ChannelSummary]:
    """
    搜索用户订阅的频道
    
    Args:
        q: 搜索关键词
        category_id: 分类筛选
        subscriber_count_min: 最小订阅数
        sort_by: 排序方式
        pagination: 分页参数
        
    Returns:
        List[ChannelSummary]: 频道搜索结果
    """
    try:
        filters = {
            "category_id": category_id,
            "subscriber_count_min": subscriber_count_min,
        }
        
        channels = await search_service.search_channels(
            current_user.id,
            query=q,
            filters=filters,
            sort_by=sort_by,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        logger.info(f"频道搜索成功", user_id=str(current_user.id), query=q, count=len(channels))
        return channels
        
    except Exception as e:
        logger.error(f"频道搜索失败: {e}", user_id=str(current_user.id), query=q)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="频道搜索失败"
        )


@router.get("/videos", response_model=List[VideoSummary], summary="视频搜索")
async def search_videos(
    q: str = Query(..., description="搜索关键词"),
    current_user: User = Depends(get_current_user),
    search_service: SearchService = Depends(get_search_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
    category_id: Optional[uuid.UUID] = Query(None, description="限制搜索的分类范围"),
    channel_id: Optional[uuid.UUID] = Query(None, description="限制搜索的频道范围"),
    published_after: Optional[str] = Query(None, description="发布时间筛选（ISO格式）"),
    duration_filter: Optional[str] = Query(None, description="时长筛选: short, medium, long"),
    view_count_min: Optional[int] = Query(None, description="最小观看数筛选"),
    sort_by: str = Query("relevance", description="排序方式: relevance, date, views, title"),
    unwatch_only: bool = Query(False, description="仅搜索未观看视频"),
) -> List[VideoSummary]:
    """
    搜索用户订阅频道的视频
    
    Args:
        q: 搜索关键词
        category_id: 分类筛选
        channel_id: 频道筛选
        published_after: 发布时间筛选
        duration_filter: 时长筛选
        view_count_min: 最小观看数
        sort_by: 排序方式
        unwatch_only: 仅未观看
        pagination: 分页参数
        
    Returns:
        List[VideoSummary]: 视频搜索结果
    """
    try:
        filters = {
            "category_id": category_id,
            "channel_id": channel_id,
            "published_after": published_after,
            "duration_filter": duration_filter,
            "view_count_min": view_count_min,
            "unwatch_only": unwatch_only,
        }
        
        videos = await search_service.search_videos(
            current_user.id,
            query=q,
            filters=filters,
            sort_by=sort_by,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        logger.info(f"视频搜索成功", user_id=str(current_user.id), query=q, count=len(videos))
        return videos
        
    except Exception as e:
        logger.error(f"视频搜索失败: {e}", user_id=str(current_user.id), query=q)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="视频搜索失败"
        )


@router.get("/suggestions", response_model=List[str], summary="获取搜索建议")
async def get_search_suggestions(
    q: str = Query(..., description="搜索关键词前缀"),
    current_user: User = Depends(get_current_user),
    search_service: SearchService = Depends(get_search_service),
    limit: int = Query(10, description="建议数量限制"),
    search_type: str = Query("all", description="搜索类型: all, channels, videos"),
) -> List[str]:
    """
    获取搜索建议和自动完成
    
    Args:
        q: 搜索关键词前缀
        limit: 建议数量限制
        search_type: 搜索类型
        
    Returns:
        List[str]: 搜索建议列表
    """
    try:
        suggestions = await search_service.get_search_suggestions(
            current_user.id,
            query_prefix=q,
            search_type=search_type,
            limit=limit,
        )
        
        logger.info(f"获取搜索建议成功", user_id=str(current_user.id), prefix=q, count=len(suggestions))
        return suggestions
        
    except Exception as e:
        logger.error(f"获取搜索建议失败: {e}", user_id=str(current_user.id), prefix=q)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取搜索建议失败"
        )


@router.get("/history", summary="获取搜索历史")
async def get_search_history(
    current_user: User = Depends(get_current_user),
    search_service: SearchService = Depends(get_search_service),
    limit: int = Query(20, description="历史记录数量限制"),
) -> List[Dict[str, Any]]:
    """
    获取用户的搜索历史记录
    
    Args:
        limit: 历史记录数量限制
        
    Returns:
        List[Dict[str, Any]]: 搜索历史列表
    """
    try:
        history = await search_service.get_search_history(
            current_user.id,
            limit=limit,
        )
        
        logger.info(f"获取搜索历史成功", user_id=str(current_user.id), count=len(history))
        return history
        
    except Exception as e:
        logger.error(f"获取搜索历史失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取搜索历史失败"
        )


@router.delete("/history", summary="清空搜索历史")
async def clear_search_history(
    current_user: User = Depends(get_current_user),
    search_service: SearchService = Depends(get_search_service),
) -> Dict[str, str]:
    """
    清空用户的搜索历史记录
    
    Returns:
        Dict[str, str]: 清空结果
    """
    try:
        await search_service.clear_search_history(current_user.id)
        
        logger.info(f"搜索历史清空成功", user_id=str(current_user.id))
        return {"message": "搜索历史已清空"}
        
    except Exception as e:
        logger.error(f"清空搜索历史失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="清空搜索历史失败"
        )


@router.post("/advanced", response_model=SearchResult, summary="高级搜索")
async def advanced_search(
    search_request: SearchRequest,
    current_user: User = Depends(get_current_user),
    search_service: SearchService = Depends(get_search_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
) -> SearchResult:
    """
    执行高级搜索（支持复杂筛选条件）
    
    Args:
        search_request: 搜索请求参数
        pagination: 分页参数
        
    Returns:
        SearchResult: 搜索结果
    """
    try:
        start_time = time.time()
        
        # 执行高级搜索
        results = await search_service.advanced_search(
            current_user.id,
            query=search_request.query,
            search_type=search_request.search_type,
            filters=search_request.filters or {},
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        search_time = time.time() - start_time
        
        # 记录高级搜索历史
        await search_service.record_search_history(
            current_user.id,
            search_request.query,
            f"advanced_{search_request.search_type}",
            results.get("total", 0)
        )
        
        logger.info(f"高级搜索执行成功", user_id=str(current_user.id), query=search_request.query)
        
        return SearchResult(
            query=search_request.query,
            total_results=results.get("total", 0),
            search_time=search_time,
            channels=results.get("channels", []),
            videos=results.get("videos", []),
            categories=results.get("categories", []),
        )
        
    except ValidationException as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"高级搜索失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="高级搜索失败"
        )